﻿
namespace VMWareLabWorkflowsDataContracts.VMWareLabDetailsDialogControls.ViewModel
{
    using System;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows;
    using System.Windows.Input;
    using Microsoft.TeamFoundation.Build.Workflow.Activities;
    using Microsoft.TeamFoundation.Lab.Workflow.Activities;
    using VMWareLabWorkflowsDataContracts.VMWareLabDetailsDialogControls.Commands;
    using VMWareLabWorkflowsDataContracts.VMWareLabDetailsDialogControls.DataContracts;

    public class DeploymentDetailsViewModel : INotifyPropertyChanged
    {
        enum MoveDirection
        {
            Up,
            Down
        }

        public ItemObservableCollection<DeploymentScript> DeploymentScripts { get; set; }

        public ObservableCollection<string> BuildAgents { get; set; } 
        public DeploymentDetails DeploymentDetails { get; set; }
        public DeploymentScript SelectedDeploymentScript { get; set; }
        public event PropertyChangedEventHandler PropertyChanged;

        public DeploymentDetailsViewModel()
        {
            try
            {
                if (VMWareWizardData.VMWareWizzardDataInstance.VMWareLabWorkflowDetails.DeploymentDetails == null)
                {
                    VMWareWizardData.VMWareWizzardDataInstance.VMWareLabWorkflowDetails.DeploymentDetails = new DeploymentDetails();
                }
                
                this.DeploymentDetails = VMWareWizardData.VMWareWizzardDataInstance.VMWareLabWorkflowDetails.DeploymentDetails;
                this.DeploymentScripts = new ItemObservableCollection<DeploymentScript>();
                this.GetBuildAgents();
                this.GetDeploymentScripts();
                this.DeploymentScripts.CollectionChanged += this.OnDeploymentCollectionChanged;
                this.DeploymentScripts.ItemPropertyChanged += this.OnDeploymentItemChanged;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error initializing deployment details!", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            
        }

        /// <summary>
        /// Gets the build agents.
        /// </summary>
        private void GetBuildAgents()
        {
            this.BuildAgents = new ObservableCollection<string>();
            foreach (var agent in VMWareWizardData.VMWareWizzardDataInstance.BuildDefinition.BuildController.Agents)
            {
                this.BuildAgents.Add(agent.Name);
            }
        }

        /// <summary>
        /// Called when [deployment scripts changed].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Collections.Specialized.NotifyCollectionChangedEventArgs"/> instance containing the event data.</param>
        private void OnDeploymentCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            this.UpdateScripts();
        }

        /// <summary>
        /// Called when [deployment item changed].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="DeploymentScript"/> instance containing the event data.</param>
        private void OnDeploymentItemChanged(object sender, ItemPropertyChangedEventArgs<DeploymentScript> e)
        {
            this.UpdateScripts();
        }

        /// <summary>
        /// Gets the deployment scripts.
        /// </summary>
        private void GetDeploymentScripts()
        {
            if (this.DeploymentDetails.Scripts == null)
            {
                return;
            }

            foreach (string script in this.DeploymentDetails.Scripts)
            {
                string[] splitScript = script.Split('#');
                if (splitScript.Any())
                {
                    var ds = new DeploymentScript();
                    ds.BuildAgentName = splitScript[0].Trim();

                    if (splitScript.Count() > 1)
                    {
                        ds.PathToExecutable = splitScript[1].Trim();
                    }
                    if (splitScript.Count() > 2)
                    {
                        ds.Arguments = splitScript[2].Trim();
                    }
                    this.DeploymentScripts.Add(ds);
                }
            }
        }

        /// <summary>
        /// Updates the scripts.
        /// </summary>
        private void UpdateScripts()
        {
            var scripts = new StringList();
            scripts.AddRange(this.DeploymentScripts.Select(ds => string.Format("{0}#{1}#{2}", ds.BuildAgentName, ds.PathToExecutable, ds.Arguments)));
            this.DeploymentDetails.Scripts = scripts;
        }

        /// <summary>
        /// Moves the grid row.
        /// </summary>
        /// <param name="direction">The direction.</param>
        private void MoveGridRow(MoveDirection direction)
        {
            DeploymentScript scriptToMove = this.SelectedDeploymentScript;
            if (scriptToMove != null)
            {
                var targetIndex = this.DeploymentScripts.IndexOf(scriptToMove);

                if (direction == MoveDirection.Up)
                {
                    targetIndex--;
                }
                else
                {
                    targetIndex++;
                }

                if (targetIndex < 0 || targetIndex > this.DeploymentScripts.Count() - 1)
                {
                    return;
                }

                this.DeploymentScripts.Remove(scriptToMove);
                this.DeploymentScripts.Insert(targetIndex, scriptToMove);
                this.SelectedDeploymentScript = scriptToMove;
            }

        }
        #region Commands

        void AddScriptExecute()
        {
            string buildAgentName = string.Empty;
            if (this.BuildAgents != null && this.BuildAgents.Count >0)
            {
                buildAgentName = this.BuildAgents.FirstOrDefault();
            }
            this.DeploymentScripts.Add(new DeploymentScript() { BuildAgentName = buildAgentName, PathToExecutable = "NewPath", Arguments = "NewArgument" });
        }

        bool CanAddScriptExecute()
        {
            return true;
        }

        public ICommand AddScript { get { return new RelayCommand(AddScriptExecute, CanAddScriptExecute); } }

        void RemoveScriptExecute()
        {
            this.DeploymentScripts.Remove(this.SelectedDeploymentScript);
        }

        bool CanRemoveScriptExecute()
        {
            return this.SelectedDeploymentScript != null;
        }

        public ICommand RemoveScript { get { return new RelayCommand(RemoveScriptExecute, CanRemoveScriptExecute); } }

        void MoveScriptUpExecute()
        {
            this.MoveGridRow(MoveDirection.Up);
        }

        bool CanMoveScriptUpExecute()
        {
            return this.SelectedDeploymentScript != null;
        }

        public ICommand MoveScriptUp { get { return new RelayCommand(MoveScriptUpExecute, CanMoveScriptUpExecute); } }

        void MoveScriptDownExecute()
        {
            this.MoveGridRow(MoveDirection.Down);
        }

        bool CanMoveScriptDownExecute()
        {
            return this.SelectedDeploymentScript != null;
        }

        public ICommand MoveScriptDown { get { return new RelayCommand(MoveScriptDownExecute, CanMoveScriptDownExecute); } }

        #endregion

        #region PropertyChanged
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
        #endregion
    }
}
